<?php
/**
 * Created by PhpStorm.
 * User: joe/Reer
 * Date: 2019-11-12
 * Time: 19:14
 */

namespace app\common\bean\builder;

use app\common\bean\BaseBean;
use app\common\bean\ListMap;
use app\common\bean\TableBean;
use app\common\exception\ParameterException;
use app\common\utils\DocParserUtil;
use app\common\utils\ExceptionUtils;
use app\common\utils\FileUtil;
use app\common\utils\StringUtil;

/**
 * Bean生成类文件
 * Class BeanManager
 * @package app\common\bean
 */
class BeanManager extends BaseBuilder
{

    public function __construct()
    {
        $type = config("database.type");
        switch ($type) {
            case "mysql":
                $this->beanBean = Mysql::getInstance();
                break;
            case "sqlsrv":
                $this->beanBean = Sqlsrv::getInstance();
                break;
            case "pgsql":
                $this->beanBean = Pgsql::getInstance();
                break;
            default:
                ExceptionUtils::throwMyException(new ParameterException());
                break;
        }
        $this->tableList = $this->beanBean->getAllTable();
    }

    /**
     * table参数接收
     * @param TableBean $tableBean
     * @return string
     * @throws \ReflectionException
     */
    public function assemblyTable(TableBean $tableBean)
    {
        $tables = $this->getTableList();
        if (!in_array($tableBean->getTableName(), $tables->getData())) {
            return 'error - table not exit';
        } else {
            $ROOT_PATH = dirname(dirname(dirname(dirname(__FILE__))));
            $this->creatBean($tableBean, $ROOT_PATH);
            $this->creatManage($tableBean, $ROOT_PATH);
            $this->creatModel($tableBean, $ROOT_PATH);
            $this->creatValidate($tableBean, $ROOT_PATH);
            $this->creatEnum($tableBean, $ROOT_PATH);
            return 'success';
        }
    }

    /**
     * table参数接收,通过form表单进行提交
     * @param TableBean $tableBean
     * @return string
     * @throws \ReflectionException
     */
    public function assemblyTableByForm(TableBean $tableBean)
    {
        $tables = $this->getTableList();
        if (!in_array($tableBean->getTableName(), $tables->getData())) {
            return 'error - table not exit';
        } else {
            $ROOT_PATH = dirname(dirname(dirname(dirname(__FILE__))));
            $this->creatBean($tableBean, $ROOT_PATH);
            $this->creatManage($tableBean, $ROOT_PATH);
            $this->creatModel($tableBean, $ROOT_PATH);
            $this->creatValidate($tableBean, $ROOT_PATH);
            $this->creatEnum($tableBean, $ROOT_PATH);
            $this->createController($tableBean, $ROOT_PATH);
            return 'success';
        }
    }

    /**
     * 自动生成Bean和Model
     * @param TableBean $tableBean
     * @return string
     */
    public function buildBeanAndModel(TableBean $tableBean)
    {
        $tables = $this->getTableList();
        if (!in_array($tableBean->getTableName(), $tables->getData())) {
            return false;
        } else {
            $ROOT_PATH = dirname(dirname(dirname(dirname(__FILE__))));
            $this->creatBean($tableBean, $ROOT_PATH);
            $this->creatModel($tableBean, $ROOT_PATH);
            return true;
        }
    }

    /**
     * table参数接收,删除bean命令自动生成的文件
     * @param TableBean $tableBean
     * @return string
     */
    public function clearBuildFiled(TableBean $tableBean)
    {
        //$tables = $this->getTableList();
        //if (!in_array($tableBean->getTableName(), $tables->getData())) {
        //return 'error - table not exit';
        //} else {
        $ROOT_PATH = dirname(dirname(dirname(dirname(__FILE__))));
        $this->delFiles($tableBean->getTableName(), $ROOT_PATH);
        return 'success';
        //}
    }

    /** 创建Bean
     * @param TableBean $tableBean
     * @param $ROOT_PATH
     * @return bool
     */
    private function creatBean(TableBean $tableBean, $ROOT_PATH)
    {
        $columns = $this->beanBean->getTableColumn($tableBean->getTableName());
        $commonBeanRoot = $ROOT_PATH . "/common/bean/";//bean类存放的文件夹
        $baseBeanFile = $commonBeanRoot . "BaseBean.php";
        if (!file_exists($baseBeanFile)) {//若不存在基础类则新建基础Bean类
            $baseBean = file_get_contents("../BaseBean.php");
            file_put_contents($baseBeanFile, $baseBean);//基础bean类
        }
        $fileName = $this->getFileName($tableBean->getTableName());
        $fileRoot = $commonBeanRoot . $fileName . ".php";

        $stringBuilder = (new StringBuilder())->concatStringEnter($this->getPhpHeader(), 0, 1)//php脚本开头 及注释
        ->concatStringEnter($this->getAppNamespace("bean"), 0, 1)//命名空间
        ->concatStringEnter($this->getClassExtends($fileName, "BaseBean"), 0, 1)
            ->concatStringEnter($this->assemblyParams($columns), 0)
            ->concatStringEnter("static \$tableName = '" . str_replace(config("database.prefix"), "", $tableBean->getTableName()) . "';")
            ->concatStringEnter("static \$alias = '{$fileName}';", 1, 2)
            ->concatStringEnter($this->assemblyGetSet($columns))
            ->concatStringEnter("}", 0);
        file_put_contents($fileRoot, $stringBuilder->getContent());
        return true;
    }

    /** 创建manage
     * @param TableBean $tableBean
     * @param $ROOT_PATH
     * @return bool
     * @throws \ReflectionException
     */
    private function creatManage(TableBean $tableBean, $ROOT_PATH)
    {
        $commonBeanRoot = $ROOT_PATH . "/common/manage/";//manage类存放的文件夹
        $fileName = $this->getFileName($tableBean->getTableName(), 'Manage');
        $fileRoot = $commonBeanRoot . $fileName . ".php";
        if (is_file($fileRoot)) return false;

        $validateName = $this->getFileName($tableBean->getTableName(), "Validate");
        $modelName = $this->getFileName($tableBean->getTableName(), "Model");
        $beanName = $this->getFileName($tableBean->getTableName(), "Bean");
        $stringBuilder = (new StringBuilder())->concatStringEnter($this->getPhpHeader(), 0, 1)//php脚本开头 及注释
        ->concatStringEnter($this->getAppNamespace("manage"), 0, 1)//命名空间
        ->concatStringEnter($this->getModuleUsePackage("validate\\{$validateName}"), 0, 1)//引入验证器
        ->concatStringEnter($this->getModuleUsePackage("model\\{$modelName}"), 0, 1)//引入model
        ->concatStringEnter($this->getModuleUsePackage("bean\\{$beanName}"), 0, 1)//引入bean
        ->concatStringEnter($this->getModuleUsePackage("bean\\ListMap"), 0, 1)//引入ListMap
        ->concatStringEnter($this->getModuleUsePackage("utils\\TimeUtil"), 0, 1)//引入TimeUtil
        ->concatStringEnter($this->getModuleUsePackage("exception\\MyException"), 0, 1)
            ->concatStringEnter("use Exception;", 0, 1)
            ->concatStringEnter($this->getClassExtends($fileName, "BaseManage"), 0, 0)
            ->concatStringEnter($this->getInstanceString($fileName), 0);


        $rc1 = new \ReflectionClass("app\common\manage\IBaseManage");
        foreach ($rc1->getMethods() as $key => $value) {
            $docParse = DocParserUtil::getInstance();
            $method = $docParse->parse($value->getDocComment());
            $paramBeanName = lcfirst($beanName);
            $method['param'] = str_replace("BaseBean \$data", $beanName . " \${$paramBeanName}", $method['param']);
            $method['return'] = str_replace("BaseBean \$data", $beanName . " \${$paramBeanName}", $method['return']);
            $stringBuilder->concatStringEnter("")
                ->concatStringEnter("/**")
                ->concatStringEnter(" * @desc {$method['desc']}")
                ->concatStringEnter(" * @param {$method['param']}")
                ->concatStringEnter(" * @return {$method['return']}")
                ->concatStringEnter(" * @throws Exception")
                ->concatStringEnter("**/");
            ($value->getName() == 'getPaginatorList') ?
                $stringBuilder->concatStringEnter("public function {$value->name}(ListMap \$listMap) {") : $stringBuilder->concatStringEnter("public function {$value->name}(\${$paramBeanName}) {");

            if ($value->getName() == 'add') {
                $stringBuilder->concatStringEnter("{$validateName}::getInstance()->goCheck({$validateName}::\$add,\${$paramBeanName}->getData());", 2)
                    ->concatStringEnter($this->getToDo(), 2)
                    ->concatStringEnter("\${$paramBeanName}->setCreatedAt(TimeUtil::getInstance()->getTimeNow());", 2)
                    ->concatStringEnter("\$result = {$modelName}::getInstance()->addDataGetInsertId(\${$paramBeanName}->getData());", 2)
                    ->concatStringEnter("\$result ?: MyException::throwMyException(\"插入数据失败\");", 2)
                    ->concatStringEnter("return \$result;", 2);
            }
            if ($value->getName() == 'edit') {
                $stringBuilder->concatStringEnter("{$validateName}::getInstance()->goCheck({$validateName}::\$edit,\${$paramBeanName}->getData());", 2)
                    ->concatStringEnter($this->getToDo(), 2)
                    ->concatStringEnter("\$result = {$modelName}::getInstance()->updatedData([{$beanName}::\$id => \${$paramBeanName}->getId()],\${$paramBeanName}->getData());", 2)
                    ->concatStringEnter("\$result ?: MyException::throwMyException(\"更新失败\");", 2)
                    ->concatStringEnter("return \$result;", 2);
            }
            if ($value->getName() == 'delete') {
                $stringBuilder->concatStringEnter("{$validateName}::getInstance()->goCheck({$validateName}::\$pkId,\${$paramBeanName}->getData());", 2)
                    ->concatStringEnter($this->getToDo(), 2)
                    ->concatStringEnter("\$result = {$modelName}::getInstance()->deleteData([{$beanName}::\$id => \${$paramBeanName}->getId()]);", 2)
                    ->concatStringEnter("\$result ?: MyException::throwMyException(\"删除失败\");", 2)
                    ->concatStringEnter("return \$result;", 2);
            }
            if ($value->getName() == 'getInfo') {
                $stringBuilder->concatStringEnter("{$validateName}::getInstance()->goCheck({$validateName}::\$pkId,\${$paramBeanName}->getData());", 2)
                    ->concatStringEnter($this->getToDo(), 2)
                    ->concatStringEnter("\$result = {$modelName}::getInstance()->selectData([{$beanName}::\$id => \${$paramBeanName}->getId()]);", 2)
                    ->concatStringEnter("\$result ?: MyException::throwMyException(\"获取信息失败\");", 2)
                    ->concatStringEnter("\${$paramBeanName}->setData(\$result);", 2)
                    ->concatStringEnter("return \${$paramBeanName};", 2);
            }
            if ($value->getName() == 'getPaginatorList') {
                $stringBuilder->concatStringEnter("\$conditionMap = new ListMap();", 2)
                    ->concatStringEnter("if(\$timeArray = TimeUtil::getInstance()->dealBetweenTime(\$listMap))", 2)
                    ->concatStringEnter("\$conditionMap->setParameter({$beanName}::\$alias.POINST.{$beanName}::\$createdAt,\$timeArray);", 2)
                    ->concatStringEnter("\$conditionMap->setAlias({$beanName}::\$alias);", 2)
                    ->concatStringEnter("\$listMap->setField({$beanName}::\$alias.ALL_FIELD);", 2)
                    ->concatStringEnter("!\$this->getParamBool(\$listMap,\"orderFieldName\") ?: \$conditionMap->setOrder(\$listMap->getParameter('orderFieldName').SPACE.\$listMap->getParameter('orderType'));", 2)
                    ->concatStringEnter($this->getToDo(), 2)
                    ->concatStringEnter("//自行选择是连表查询还是单表查询,默认单表", 2)
                    ->concatStringEnter("//\$resultMap = {$modelName}::getInstance()->getJoinList(\$conditionMap);", 2)
                    ->concatStringEnter("\$resultMap = {$modelName}::getInstance()->getList(\$conditionMap);", 2)
                    ->concatStringEnter("\$resultMap?:MyException::throwMyException(\"查询数据失败\");", 2)
                    ->concatStringEnter("return \$resultMap;", 2);
            }
            $stringBuilder->concatStringEnter("}");
        }
        $stringBuilder->concatStringEnter("}", 0);
        file_put_contents($fileRoot, $stringBuilder->getContent());
        return true;
    }

    /** 创建model
     * @param TableBean $tableBean
     * @param $ROOT_PATH
     * @return bool
     */
    private function creatModel(TableBean $tableBean, $ROOT_PATH)
    {
        $commonBeanRoot = $ROOT_PATH . "/common/model/";//model类存放的文件夹
        $fileName = $this->getFileName($tableBean->getTableName(), 'Model');
        $fileRoot = $commonBeanRoot . $fileName . ".php";
        if (is_file($fileRoot)) return false;

        $stringBuilder = (new StringBuilder())->concatStringEnter($this->getPhpHeader(), 0, 1)//php脚本开头 及注释
        ->concatStringEnter($this->getAppNamespace("model"), 0, 2)//命名空间
        ->concatStringEnter($this->getClassExtends($fileName, "BaseModel"), 0, 0)
            ->concatStringEnter("protected \$table = '{$tableBean->getTableName()}';")
            ->concatStringEnter($this->getInstanceString($fileName), 0)
            ->concatStringEnter("}", 0);
        file_put_contents($fileRoot, $stringBuilder->getContent());
        return true;

    }

    /** 创建validate
     * @param TableBean $tableBean
     * @param $ROOT_PATH
     * @return bool
     */
    private function creatValidate(TableBean $tableBean, $ROOT_PATH)
    {
        $commonBeanRoot = $ROOT_PATH . "/common/validate/";//model类存放的文件夹
        $fileName = $this->getFileName($tableBean->getTableName(), 'Validate');
        $beanName = $this->getFileName($tableBean->getTableName());
        $columns = $this->beanBean->getTableColumn($tableBean->getTableName());
        $baseValidateFile = $commonBeanRoot . "BaseValidate.php";
        if (!file_exists($baseValidateFile)) {//若不存在基础类则新建基础Bean类
            $baseBean = file_get_contents("BaseValidate.php");
            file_put_contents($baseValidateFile, $baseBean);//基础bean类
        }

        $validateSence = '';
        $fileRoot = $commonBeanRoot . $fileName . ".php";
        if (is_file($fileRoot)) {
            $validateClass = fopen($fileRoot, "r") or die("Unable to open file!");
            $content = fread($validateClass, filesize($fileRoot));
            $validateSence = substr($content, strpos($content, '$this->scene'), strripos($content, '];') - strpos($content, '$this->scene') + 2);
            fclose($validateClass);
        }
        $stringBuilder = (new StringBuilder())
            ->concatStringEnter($this->getPhpHeader(), 0, 1)//php脚本开头 及注释
            ->concatStringEnter($this->getAppNamespace("validate"), 0, 2)//命名空间
            ->concatStringEnter($this->getModuleUsePackage("bean\\{$beanName}"), 0, 2)//命名空间
            ->concatStringEnter($this->getClassExtends($fileName, "BaseValidate"), 0, 1)//类名及基层基础Bean类
            ->concatStringEnter($this->validateFields($tableBean, $columns, $beanName, $validateSence), 0, 2)
            ->concatStringEnter("}", 0);

        file_put_contents($fileRoot, $stringBuilder->getContent());
        return true;
    }

    /** 参数组装  protected $id = "id"; //主键
     * @param ListMap $columns
     * @return string
     */
    private function assemblyParams(ListMap $columns)
    {
        $stringBuilder = new StringBuilder();
        $baseBean = new BaseBean();
        foreach ($columns->getList() as $item) {//组装好所有变量
            $baseBean->setData($item);
            $fieldName = $baseBean->getParameter("COLUMN_NAME");
            $param = StringUtil::getInstance()->convertUnderline($fieldName);//变量名
            $stringBuilder->concatStringEnter("static \${$param} = '{$fieldName}'; //{$baseBean->getParameter('COLUMN_COMMENT')}");
        }
        return $stringBuilder->getContent();
    }

    /**组装get、set函数
     * @param ListMap $columns
     * @return string
     */
    private function assemblyGetSet(ListMap $columns)
    {
        $stringBuilder = (new StringBuilder());
        $stringBuilder->concatStringEnter("");

        $baseBean = new BaseBean();
        foreach ($columns->getList() as $item) {
            $baseBean->setData($item);
            $fieldName = $baseBean->getParameter("COLUMN_NAME");
            $param = StringUtil::getInstance()->convertUnderline($fieldName, false);
            $functionParam = ucfirst($param); //get 、set 后面字母大写
            $stringBuilder->concatStringEnter("public function get{$functionParam}(){")
                ->concatStringEnter("return \$this->getParameter(self::\${$param});", 2)
                ->concatStringEnter("}", 1, 2)
                ->concatStringEnter("public function set{$functionParam}(\${$param}){")
                ->concatStringEnter("\$this->setParameter('{$fieldName}',\${$param});", 2)
                ->concatStringEnter("}", 1, 2);
        }
        return $stringBuilder->getContent();
    }

    /**验证参数封装  protected $id = "id"; //主键
     * @param TableBean $tableBean
     * @param ListMap $columns
     * @param $beanName
     * @param $validateSence
     * @return string|bool
     */
    private function validateFields(TableBean $tableBean, ListMap $columns, $beanName, $validateSence)
    {
        $stringBuilder = (new StringBuilder())
            ->concatStringEnter("static \$all = 'all';")
            ->concatStringEnter("static \$add = 'add';")
            ->concatStringEnter("static \$edit = 'edit';")
            ->concatStringEnter("static \$pkId = 'id';", 1, 2)
            ->concatStringEnter("public function __construct(array \$rules = [], array \$message = [], array \$field = [])")
            ->concatStringEnter("{")
            ->concatStringEnter("parent::__construct(\$rules, \$message, \$field);", 2)
            ->concatStringEnter("\$this->rule = [", 2);

        $baseBean = new BaseBean();
        foreach ($columns->getList() as $item) {//组装好所有变量
            $baseBean->setData($item);
            $fieldName = $baseBean->getParameter("COLUMN_NAME");
            $param = StringUtil::getInstance()->convertUnderline($fieldName);

            $stringBuilder->concatStringEnter("{$this->getTab(3)} {$beanName}::\${$param} => 'require", 0, 0);
            if ($item['DATA_TYPE'] == 'varchar' && isset($item['CHARACTER_MAXIMUM_LENGTH'])) {
                $stringBuilder->concatStringEnter("|max:{$item['CHARACTER_MAXIMUM_LENGTH']}", 0, 0);
            }
            #字段具有唯一索引的，验证器规则对应验证唯一性
            if ($item['COLUMN_KEY'] == 'UNI') {
                $stringBuilder->concatStringEnter("|unique:{$tableBean->getTableName()}', //{$baseBean->getParameter('COLUMN_COMMENT')}{$this->getEnter()}");
            } else {
                $stringBuilder->concatStringEnter("', //{$baseBean->getParameter('COLUMN_COMMENT')}{$this->getEnter()}", 0, 0);
            }
        }
        $stringBuilder->concatStringEnter("];", 2)
            ->concatStringEnter("\$this->message = [", 2);
        $baseBean = new BaseBean();
        foreach ($columns->getList() as $item) {//组装好所有变量
            $baseBean->setData($item);
            $fieldName = $baseBean->getParameter("COLUMN_NAME");
            $param = StringUtil::getInstance()->convertUnderline($fieldName);
            $stringBuilder->concatStringEnter("{$beanName}::\${$param}.POINST.\"require \" => '{$fieldName}必须', //{$baseBean->getParameter('COLUMN_COMMENT')}", 3);
        }
        $stringBuilder->concatStringEnter("];", 2);
        if (!strlen($validateSence)) {
            $stringBuilder->concatStringEnter("\$this->scene = [", 2)
                ->concatStringEnter("self::\$all => [", 3);
            $baseBean = new BaseBean();
            #全部
            foreach ($columns->getList() as $item) {//组装好所有变量
                $baseBean->setData($item);
                $fieldName = $baseBean->getParameter("COLUMN_NAME");
                $param = StringUtil::getInstance()->convertUnderline($fieldName);
                $stringBuilder->concatStringEnter("{$beanName}::\${$param},", 4);
            }
            $stringBuilder->concatStringEnter("],", 3);
            #curd验证场景
            $stringBuilder->concatStringEnter($tableBean->getCurdValidateScene($beanName), 2);
            $stringBuilder->concatStringEnter("];", 2);
        } else {
            $stringBuilder->concatStringEnter($validateSence, 2);
        }
        $stringBuilder->concatStringEnter("}", 1);
        return $stringBuilder->getContent();
    }

    /**创建枚举类
     * @param TableBean $tableBean
     * @param $ROOT_PATH
     * @return bool
     */
    private function creatEnum(TableBean $tableBean, $ROOT_PATH)
    {
        $columns = $this->beanBean->getTableColumn($tableBean->getTableName());
        $commonBeanRoot = $ROOT_PATH . "/common/enum/";//bean类存放的文件夹

        #如果前端有传递枚举量数组过来，则按前端的生成,没有则按命令行方式生成
        if ($tableBean->getEnumList()) {
            foreach ($tableBean->getEnumList() as $item) {
                $listMap = new ListMap();
                $listMap->setData($item['data']);
                $fieldName = $tableBean->getTableName() . "_" . $listMap->getField();

                $kvList = $listMap->getParameter("kvList");
                $kvList = is_array($kvList) ? $kvList : array();
                $fileName = $this->getFileName($fieldName, 'Enum');
                $fileRoot = $commonBeanRoot . $fileName . ".php";
                if (is_file($fileRoot)) return true;
                $stringBuilder = (new StringBuilder())
                    ->concatStringEnter($this->getPhpHeader(), 0)//php脚本开头 及注释
                    ->concatStringEnter($this->getAppNamespace("enum"), 0)//命名空间
                    ->concatStringEnter($this->getClassExtends($fileName, "BaseEnumAbtract"), 0, 2);//类名及基层基础Bean类

                $funcContent = (new StringBuilder())
                    ->concatStringEnter("\$type = intval(\$type);", 1)
                    ->concatStringEnter("\$arrayName = self::getArrayName();", 2)
                    ->concatStringEnter("return isset(\$arrayName[\$type]) ? \$arrayName[\$type] : '状态出错';", 2)
                    ->getContent();

                foreach ($kvList as $kvItem) {
                    $stringBuilder->concatStringEnter("CONST " . $kvItem['key'] . " = {$kvItem['value']};", 1, 2);
                }
                $stringBuilder->concatStringEnter($this->getCommentAndFunctionTpl([
                    'desc' => '根据类型获取对应名称',
                    'param' => '$type',
                    'return' => 'mixed'
                ], true, 'getName', $funcContent));

                $funcBuilder = (new StringBuilder())->concatStringEnter("return [");
                foreach ($kvList as $kvItem) {
                    $listItem = new ListMap();
                    $listItem->setData($kvItem);
                    $funcBuilder->concatStringEnter("self::{$listItem->getParameter('key')} => \"{$listItem->getParameter('text')}\",", 3);
                }
                $funcBuilder->concatStringEnter("];", 2);

                $stringBuilder->concatStringEnter($this->getCommentAndFunctionTpl([
                    'desc' => '获取类型、名称数组',
                    'return' => 'mixed'
                ], true, 'getArrayName', $funcBuilder->getContent()));
                $content = $stringBuilder->concatStringEnter("}")->getContent();
                file_put_contents($fileRoot, $content);
            }
        } else {
            foreach ($columns->getList() as $item) {
                $fieldName = $item['TABLE_NAME'] . "_" . $item['COLUMN_NAME'];
                $fileName = $this->getFileName($fieldName, 'Enum');
                $fileRoot = $commonBeanRoot . $fileName . ".php";
                if ($item['DATA_TYPE'] == 'tinyint' && !file_exists($fileRoot)) {
                    $content = $this->getPhpHeader() . $this->getEnter();//php脚本开头 及注释
                    $content .= $this->getAppNamespace("enum") . $this->getEnter(2);//命名空间
                    $content .= $this->getClassExtends($fileName, "BaseEnumAbtract");//类名及基层基础Bean类
                    $content .= $this->getTab(2) . $this->getEnter();

                    $funcContent = "{$this->getEnter()}{$this->getTab(2)}\$type = intval(\$type);{$this->getEnter()}{$this->getTab(2)}\$arrayName = self::getArrayName();{$this->getEnter()}{$this->getTab(2)}return isset(\$arrayName[\$type]) ? \$arrayName[\$type] : '状态出错';{$this->getEnter()}{$this->getTab(2)}";
                    $content .= $this->getCommentAndFunctionTpl([
                        'desc' => '根据类型获取对应名称',
                        'param' => '$type',
                        'return' => 'mixed'
                    ], true, 'getName', $funcContent);

                    $funcContent = "{$this->getEnter()}{$this->getTab(2)}return [{$this->getEnter()}{$this->getTab(2)}];{$this->getEnter()}{$this->getTab(2)}";
                    $content .= $this->getCommentAndFunctionTpl([
                        'desc' => '获取类型、名称数组',
                        'return' => 'mixed'
                    ], true, 'getArrayName', $funcContent);
                    $content .= "}";
                    file_put_contents($fileRoot, $content);
                }
            }
        }
        return true;
    }

    /**
     * @desc 创建控制器
     * @param TableBean $tableBean
     * @param $ROOT_PATH
     * @return bool
     */
    public function createController(TableBean $tableBean, $ROOT_PATH)
    {
        if (!StringUtil::getInstance()->is_true($tableBean->getParameter("isCreateController")))
            return;
        $module = $tableBean->getParameter("module");
        $commonBeanRoot = $ROOT_PATH . "/{$module}/controller/";//manage类存放的文件夹
        $fileName = $this->getFileName($tableBean->getTableName(), '');
        $fileRoot = $commonBeanRoot . $fileName . ".php";
        if (is_file($fileRoot)) return false;
        $validateName = $this->getFileName($tableBean->getTableName(), "Validate");
        $modelName = $this->getFileName($tableBean->getTableName(), "Model");
        $beanName = $this->getFileName($tableBean->getTableName(), "Bean");
        $lcBeanName = lcfirst($beanName);
        $manageName = $this->getFileName($tableBean->getTableName(), "Manage");

        $beanMapName = lcfirst($this->getFileName($tableBean->getTableName(), "Map"));
        $tableNameTF = lcfirst($this->getFileName($tableBean->getTableName(), ""));

        #创建beanList方法
        $content = (new StringBuilder())
            ->concatStringEnter($this->getPhpHeader(), 0)//php脚本开头 及注释
            ->concatStringEnter($this->getAppNamespace("controller", "\\{$module}\\"), 0)//命名空间
            ->concatStringEnter($this->getModuleUsePackage("validate\\{$validateName}"), 0)//引入验证器
            ->concatStringEnter($this->getModuleUsePackage("model\\{$modelName}"), 0)//引入model
            ->concatStringEnter($this->getModuleUsePackage("bean\\{$beanName}"), 0)//引入bean
            ->concatStringEnter($this->getModuleUsePackage("manage\\{$manageName}"), 0)//引入manage
            ->concatStringEnter($this->getModuleUsePackage("bean\\ListMap"), 0)//引入ListMap
            ->concatStringEnter($this->getModuleUsePackage("utils\\TimeUtil"), 0)//引入TimeUtil
            ->concatStringEnter($this->getModuleUsePackage("utils\\ExitJsonUtil"), 0)//引入ExitJsonUtil
            ->concatStringEnter($this->getModuleUsePackage("controller\\AdminController"), 0)//引入基类控制器
            ->concatStringEnter($this->getModuleUsePackage("exception\\MyException"), 0)
            ->concatStringEnter("use Exception;", 0, 2)//引入Exception
            ->concatStringEnter($this->getClassExtends($fileName, "AdminController"), 0)//引入继承基类控制器
            ->getContent();

        #创建beanList方法
        $funcContent = (new StringBuilder())->getTab(2)->concatStringEnter("\$listMap = new ListMap();", 0)
            ->concatStringEnter("\$listMap->setData(\$this->getParams);", 2)
            ->concatStringEnter("\${$beanMapName} = {$manageName}::getInstance()->getPaginatorList(\$listMap);", 2)
//            ->concatStringEnter("\$categorySelect = ProductCategoryManage::getInstance()->getCategorySelect();", 2)
//            ->concatStringEnter("\$this->assign('categorySelect',\$categorySelect);", 2)
            ->concatStringEnter("\$this->assign(\"{$tableNameTF}List\",\${$beanMapName}->getList());", 2)
            ->concatStringEnter("\$this->assign(\"currentPage\",\${$beanMapName}->getCurrentPage());", 2)
            ->concatStringEnter("\$this->assign(\"totalCount\",\${$beanMapName}->getTotalCount());", 2)
//            ->concatStringEnter("\$this->assign('isUpDownSelect',ProductIsUpEnum::getArrayName());", 2)
            ->concatStringEnter("return \$this->fetch();", 2)
            ->getContent();

        $content .= $this->getCommentAndFunctionTpl([
            'desc' => $tableBean->getTableName() . '列表',
            'return' => 'mixed',
            'throws' => 'Exception'
        ], false, StringUtil::getInstance()->convertUnderline($tableBean->getTableName()) . "List", $funcContent);

        #创建addBean方法
        $funcContent = (new StringBuilder())->getTab(2)->concatStringEnter("", 0)
            ->concatStringEnter("if(request()->isPost()){", 2)
            ->concatStringEnter("\${$lcBeanName} = new {$beanName}();", 3)
            ->concatStringEnter("\${$lcBeanName}->setData(\$this->postParams);", 3)
            ->concatStringEnter("\$result = {$manageName}::getInstance()->add(\${$lcBeanName});", 3)
            ->concatStringEnter("ExitJsonUtil::getInstance()->exitData(\$result);", 3)
            ->concatStringEnter("}", 2)
            ->concatStringEnter("return \$this->fetch();", 2)
            ->getContent();

        $content .= $this->getCommentAndFunctionTpl([
            'desc' => '添加' . $tableBean->getTableName(),
            'throws' => 'Exception'
        ], false, "add" . ucfirst($tableNameTF), $funcContent);

        #创建editBean方法
        $funcContent = (new StringBuilder())->getTab(2)->concatStringEnter("", 0)
            ->concatStringEnter("\${$lcBeanName} = new {$beanName}();", 2)
            ->concatStringEnter("\${$lcBeanName}->setData(\$this->getParams);", 2)
            ->concatStringEnter("if(request()->isPost()){", 2)
            ->concatStringEnter("\${$lcBeanName} = new {$beanName}();", 3)
            ->concatStringEnter("\${$lcBeanName}->setData(\$this->postParams);", 3)
            ->concatStringEnter("\$result = {$manageName}::getInstance()->add(\$" . lcfirst($beanName) . ");", 3)
            ->concatStringEnter("ExitJsonUtil::getInstance()->exitData(\$result);", 3)
            ->concatStringEnter("}", 2)
            ->concatStringEnter("\${$lcBeanName} = {$manageName}::getInstance()->getInfo(\${$lcBeanName});", 2)
            ->concatStringEnter("\$this->assign('{$tableNameTF}',\${$lcBeanName}->getData());", 2)
            ->concatStringEnter("return \$this->fetch();", 2)
            ->getContent();

        $content .= $this->getCommentAndFunctionTpl([
            'desc' => '编辑' . $tableBean->getTableName(),
            'throws' => 'Exception'
        ], false, "edit" . ucfirst($tableNameTF), $funcContent);

        #创建delBean方法
        $funcContent = (new StringBuilder())->getTab(2)->concatStringEnter("", 0)
            ->concatStringEnter("\${$lcBeanName} = new {$beanName}();", 2)
            ->concatStringEnter("\${$lcBeanName}->setData(\$this->getParams);", 2)
            ->concatStringEnter("\$result = {$manageName}::getInstance()->delete(\$" . lcfirst($beanName) . ");", 2)
            ->concatStringEnter("ExitJsonUtil::getInstance()->exitData(\$result);", 2)
            ->getContent();

        $content .= $this->getCommentAndFunctionTpl([
            'desc' => '删除' . $tableBean->getTableName(),
            'throws' => 'Exception'
        ], false, "del" . ucfirst($tableNameTF), $funcContent);


        $content .= "{$this->getEnter(2)}}";
        file_put_contents($fileRoot, $content);

        $tplDir = $ROOT_PATH . "/common/view/curd_tpl";
        $controllerViewDir = $ROOT_PATH . "/{$module}/view/{$tableBean->getTableName()}";
        is_dir($controllerViewDir) ?: mkdir($controllerViewDir);

        $tplStr = file_get_contents("{$tplDir}/add_tpl.html");
        file_put_contents("{$controllerViewDir}/add_{$tableBean->getTableName()}.html", $tplStr);
        $tplStr = file_get_contents("{$tplDir}/edit_tpl.html");
        file_put_contents("{$controllerViewDir}/edit_{$tableBean->getTableName()}.html", $tplStr);
        $tplStr = file_get_contents("{$tplDir}/list_tpl.html");
        $tplStr = str_replace("addBean", "add" . StringUtil::getInstance()->convertUnderline($tableBean->getTableName(), true), $tplStr);
        $tplStr = str_replace("beanList", $tableNameTF . "List", $tplStr);
        file_put_contents("{$controllerViewDir}/{$tableBean->getTableName()}_list.html", $tplStr);

        return true;
    }

    /**
     * @desc 获取注释和方法
     * @param array $param
     * @param bool $isStaticFunc
     * @param $funcName
     * @param string $funcConent
     * @return string
     */
    private function getCommentAndFunctionTpl($param = array(), $isStaticFunc = false, $funcName, $funcConent = "")
    {
        $stringBuilder = (new StringBuilder())->concatStringEnter("/**");
        foreach ($param as $key => $value) {
            if ($key == 'desc') {
                $stringBuilder->concatStringEnter(" * @desc " . $value);
            } else if ($key == 'param') {
                $stringBuilder->concatStringEnter(" * @param " . $value);
            } else if ($key == 'return') {
                $stringBuilder->concatStringEnter(" * @return " . $value);
            } else if ($key == 'throws') {
                $stringBuilder->concatStringEnter(" * @throws " . $value);
            }
        }
        $stringBuilder = $stringBuilder->concatStringEnter("*/");

        $func = "public ";
        !$isStaticFunc ?: $func .= "static";
        $func .= " function {$funcName}(";
        foreach ($param as $key => $value) {
            $params = '';
            if ($key == 'param') {
                $params .= $value . ",";
            }
            $params = substr($params, 0, strlen($params) - 1);
            $func .= $params;
        }
        $func .= ")";
        $stringBuilder->concatStringEnter($func)
            ->concatStringEnter("{")
            ->concatStringEnter("// TODO: Implement getName() method.", 2)
            ->concatStringEnter($funcConent)
            ->concatStringEnter("}");
        return $stringBuilder->getContent();
    }


    /**
     * 删除生成的bean，model...
     * @param $tableName
     * @param $ROOT_PATH
     */
    private function delFiles($tableName, $ROOT_PATH)
    {
        $columns = $this->beanBean->getTableColumn($tableName);
        $commonBeanRoot = $ROOT_PATH . "/common/bean/";//bean类存放的文件夹
        $fileName = $this->getFileName($tableName, "Bean", ".php");
        $aimFile = $commonBeanRoot . $fileName;
        if (file_exists($aimFile)) {//若不存在基础类则新建基础Bean类
            @unlink($aimFile);
        }
        $commonBeanRoot = $ROOT_PATH . "/common/manage/";//model类存放的文件夹
        $fileName = $this->getFileName($tableName, 'Manage', ".php");
        $aimFile = $commonBeanRoot . $fileName;
        if (file_exists($aimFile)) {//若不存在基础类则新建基础Manager类
            @unlink($aimFile);
        }
        $commonBeanRoot = $ROOT_PATH . "/common/model/";//model类存放的文件夹
        $fileName = $this->getFileName($tableName, 'Model', ".php");
        $aimFile = $commonBeanRoot . $fileName;
        if (file_exists($aimFile)) {//若不存在基础类则新建基础Model类
            @unlink($aimFile);
        }
        $commonBeanRoot = $ROOT_PATH . "/common/validate/";//model类存放的文件夹
        $fileName = $this->getFileName($tableName, 'Validate', ".php");
        $aimFile = $commonBeanRoot . $fileName;
        if (file_exists($aimFile)) {//若不存在基础类则新建基础Validate类
            @unlink($aimFile);
        }
        foreach (config("project.modules") as $item){
            $commonBeanRoot = $ROOT_PATH . "/{$item}/controller/";//model类存放的文件夹
            $fileName = $this->getFileName($tableName, '', ".php");
            $aimFile = $commonBeanRoot . $fileName;
            if (file_exists($aimFile)) {//若不存在基础类则新建基础Manager类
                @unlink($aimFile);
            }
        }

        foreach (config("project.modules") as $item){
            $commonBeanRoot = $ROOT_PATH . "/{$item}/view/{$tableName}";//view存放的文件夹
            FileUtil::getInstance()->delDir($commonBeanRoot);
        }

        $commonBeanRoot = $ROOT_PATH . "/common/enum/";//bean类存放的文件夹
        foreach ($columns->getList() as $item) {
            $fieldName = $item['TABLE_NAME'] . "_" . $item['COLUMN_NAME'];
            $fileName = $this->getFileName($fieldName, 'Enum', ".php");
            $aimFile = $commonBeanRoot . $fileName;
            if ($item['DATA_TYPE'] == 'tinyint' && file_exists($aimFile)) {
                @unlink($aimFile);
            }
        }
    }

}